package main

import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"

	// "github.com/cheggaaa/pb"
	pb "github.com/cheggaaa/pb/v3"
	"github.com/gen2brain/dlgs"
	"github.com/xor-gate/goexif2/exif"
	"github.com/xor-gate/goexif2/mknote"
)

var (
	ExistedDir  = make(map[string]bool)
	IfSortByMon = false
	baseDir     = ""
	Counteri    = 0
	Gio         = make(chan Pack, 30)
	files       = make(map[string]string)
	srcDir      string
	dstDir      string
)

func C() {
	defer func() {
		Counteri++
	}()
	fmt.Print("Deal ph:", Counteri, "           \r")
}

func GetTimeToDir(t time.Time) string {
	if baseDir == "" {
		dlgs.Error("错误信息", "必须设置整理目录")
		os.Exit(1)
	}
	monDir := fmt.Sprintf("%d-%d", t.Year(), t.Month())
	b := filepath.Join(baseDir, monDir)

	// if _, ok := ExistedDir[b]; !ok {
	if _, err := os.Stat(b); err != nil {
		if err := os.MkdirAll(b, os.ModePerm); err != nil {
			log.Fatal(err)
		}
	}

	// ExistedDir[b] = true
	// }
	return b
}

func ExtractTime(file string) (time.Time, error) {

	f, err := os.Open(file)
	defer f.Close()
	if err != nil {
		log.Fatal(err)
	}

	// Optionally register camera makenote data parsing - currently Nikon and
	// Canon are supported.
	exif.RegisterParsers(mknote.All...)

	x, err := exif.Decode(f)
	if err != nil {
		log.Fatal(err)
	}
	return x.DateTime()

}

func setTimeRange() (st, et time.Time, useAll bool, err error) {
	st, u, err := dlgs.Date("选择一个时间区间然后归类照片", "选择开始时间(默认两年前)", time.Now().AddDate(-3, 0, 0))
	et, u2, err := dlgs.Date("选择一个时间区间然后归类照片", "选择结束时间(默认今天)", time.Now())
	if u && u2 {
		useAll = true
	} else {
		err = errors.New("没有选择任何时间，取消归类")
	}
	return
}

func setDirectorName() (name string, err error) {
	name, u, err := dlgs.File("符合时间的照片移动到哪个目录", "", true)
	if !u {
		err = errors.New("没有设置一个 合法的目录")
	}
	return
}

func setSourceImagesDirectorName() (name string, err error) {
	name, u, err := dlgs.File("从哪个目录开始递归分类照片", "", true)
	if _, err := os.Stat(name); err != nil {
		if _, err := os.Stat("/Volumes"); err == nil {
			fss, err := ioutil.ReadDir("/Volumes")
			if err != nil {
				return "", err
			}
			for _, f := range fss {
				if _, err := os.Stat(filepath.Join("/Volumes", f.Name(), name)); err == nil {
					return filepath.Join("/Volumes", f.Name(), name), nil
					// return "", nil
				}
			}

		}
	}
	if !u {
		err = errors.New("没有设置一个 合法的目录")
	}
	return
}

type Pack struct {
	info os.FileInfo
	path string
}

func DoSingle(pack Pack) {
	// defer w.Done()
	info := pack.info
	path := pack.path
	if !info.IsDir() && strings.HasSuffix(strings.ToLower(info.Name()), ".jpg") {
		if takeTime, err := ExtractTime(path); err == nil {
			files[path] = filepath.Join(GetTimeToDir(takeTime), info.Name())
			// C()
		}
	}
}

func DoSome() {
	// var w sync.WaitGroup
	c := 0
	for {
		c++
		pack := <-Gio

		if pack.path == "[EXIT]" {
			break
		}
		// w.Add(1)
		DoSingle(pack)
		// if c == 30 {
		// 	w.Wait()
		// 	w = sync.WaitGroup{}
		// 	c = 0
		// }
	}
}

func main() {

	flag.StringVar(&srcDir, "s", "", "src dir")
	flag.StringVar(&dstDir, "d", "", "dst dir")
	flag.Parse()
	var err error
	if srcDir == "" {
		srcDir, err = setSourceImagesDirectorName()
	}
	if err != nil {
		log.Fatal(err)
	}
	if dstDir == "" {
		dstDir, err = setDirectorName()
	}
	if err != nil {
		log.Fatal(err)
	}
	baseDir = dstDir
	fmt.Println(srcDir, "=>", dstDir)
	go DoSome()
	err = filepath.Walk(srcDir, func(path string, info os.FileInfo, err error) error {
		C()
		Gio <- Pack{
			path: path,
			info: info,
		}
		return nil

	})
	if err != nil {
		log.Fatal(err)
		dlgs.Error("消息", err.Error())
	}

	tmpF, _ := os.Stat(".")
	Gio <- Pack{
		path: "[Exit]",
		info: tmpF,
	}
	if len(files) > 0 {
		bar := pb.StartNew(len(files))
		for src, dst := range files {
			// fmt.Println(src, "-->", dst)
			if err := os.Rename(src, dst); err != nil {
				log.Println("归类错误信息", err.Error())
			}
			bar.Increment()
		}
		bar.Finish()

	} else {
		dlgs.Info("消息", "没有找到任何照片在 目录符合时间")
	}

	// log.Println("choose time", out.String())

	// ExtractTime("Res\\test.JPG")
}
